`ifndef EV10AQ190_DRIVE_SVH
`define EV10AQ190_DRIVE_SVH

class ev10aq190_driver;
    /*
     * 静态属性
     */
    virtual ev10aq190_bfm bfm;

    function new(virtual ev10aq190_bfm b);
        bfm = b;
    endfunction

    /*-------------------------------------------------------------------------
    //description   : 
    //parameter     : sine_freq:
    //                ad_bit : ad的位宽
    //others        :
    -------------------------------------------------------------------------*/
    extern task make_sine_wave(int sine_freq, int ad_bit, int offset);

    /*-------------------------------------------------------------------------
    //description   : 产生指定宽度的高电平信号. 单位:  时钟周期 (1ns)
    //parameter     : offset: 相对 trg_in 的偏移时间
    //                width: 高电平宽度
    //                num: 有几个高电平脉冲
    //                interval: 高电平脉冲的间隔时间
    //                default_value: AD默认值
    //                mode: USE_ADC_CLK, 使用adc_clk发送数据
    //                      1GHZ, 按照1Ghz频率发送数据    
    //others        :
    -------------------------------------------------------------------------*/
    extern task make_pulse(int offset, int width, int num, int interval, int  default_value);
    extern task make_increase_serial(string mode);
endclass

task ev10aq190_driver::make_sine_wave(int sine_freq, int ad_bit, int offset);
    int len = 1000_000_000 / sine_freq;
    real space_data[] = new[len];  // 0 - 2*pi 等分
    real result[] = new[len];

    for(int i = 0; i < len; i = i + 1 )
        space_data[i] = 2*3.1415926/len*i;

    for(int i = 0; i < len; i = i + 1 )
        result[i] = $ceil($sin(space_data[i]) * $pow(2, ad_bit-1) + offset)-1;

    forever
    begin
        for(int i = 0; i < $size(result); i = i + 1 )
        begin
            @ (bfm.adc_clk);
            bfm.adc_din = result[i];
        end
    end
endtask

task ev10aq190_driver::make_pulse(int offset, int width, int num, int interval, int default_value);
    logic [09:00] temp = 10'h300;
    while(1)
    begin
        bfm.adc_din = default_value;
        @(posedge bfm.trg_in);
        for(int i = 0; i < offset/1; i = i + 1 )
        begin
            bfm.adc_din = i%14;
            #1ns;
        end
        repeat(num)
        begin
            bfm.adc_din = temp;
            for(int i = 0; i < width; i = i + 1 )
            begin
                bfm.adc_din = temp + i + 1; #1ns;
            end
            for(int i = 0; i < interval; i = i + 1 )
            begin
                bfm.adc_din = default_value; #1ns;
            end
        end
        bfm.adc_din = default_value; 
    end
endtask

task ev10aq190_driver::make_increase_serial(string mode);
    while(1)
    begin
        bfm.adc_din = 0;
        @(posedge bfm.trg_in);
        for(int i = 0; i < 1000_000_000; i = i + 1 )
        begin
            if(mode == "1GHz")
                #1ns;
            else if(mode == "USE_ADC_CLK")
                @(bfm.adc_clk);;

            bfm.adc_din = i;
        end
    end
endtask

`endif
